使用者无权访问目标对象
中间加代理，通过代理做授权和控制

## 示例

科学上网  
明星经纪人

```js
class ReadImg {
  constructor(fileName) {
    this.fileName = fileName;
    this.loadFromDisk(); //初始化即从硬盘中加载，模拟
  }

  display() {
    console.log("display", this.fileName);
  }

  loadFromDisk() {
    console.log("load", this.fileName);
  }
}

class ProxyImg {
  constructor(fileName) {
    this.realImg = new ReadImg(fileName);
  }

  display() {
    this.realImg.display();
  }
}

let proxyImg = new ProxyImg("1.png");
proxyImg.display();
```

```html
// 网页事件代理
<div id="div1">
  <a href="#">a</a>
  <a href="#">b</a>
</div>

<script>
  div1.addEventListener("click", function () {
    var target = e.target;
    if (e.nodeName === "a") {
      alert(target.innerHTML);
    }
  });
</script>
```

```js
// $.proxy

$("#div1").click(function () {
  // this 符合期望
  $(this).addClass("red");
});

$("#div1").click(function () {
  setTimeout(function () {
    // this 不符合期望
    $(this).addClass("red");
  }, 1000);
});



// 可以用如下方式解决

$("#div1").click(function () {
    var _this = this;
  setTimeout(function () {
    $(_this).addClass("red");
  }, 1000);
});


// 但推荐使用 ＄.proxy 解决，这样就少定义一个变量
$("#div1").click(function () {
  setTimeout($.proxy(function () {
    // this 不符合期望
    $(this).addClass("red");
  }, this), 1000);
});
```


```js 
// 明星
let star = {
    name: '张三',
    age: 25,
    phone: '18922222222'
}

// 经纪人
let agent = new Proxy(start, {
    get: function(target, key){
        if(key === 'phone')return '13599999999'; // 返回经纪人自己的
        if(key === price) return 12000; // 明星不报价，经纪人报价

        return target[key]
    }

    set: function(target, key, val){
        if(key === 'customPrice'){
            if(val < 100000) throw new Error('我们只拍10票房以上的电影');
            else target[key] = val; return true;
        }
    }
})
```

场景

网页事件代理
jquery $.proxy
es6 proxy

### 设计原则验证

代理类和目标类分离，隔离开目标类和使用者  
符合开放封闭原则

## 代理模式 vS 适配器模式

- 适配器模式：提供一个不同的接口（如不同版本的插头）
- 代理模式：提供一模一样的接口

## 代理模式 vS 装饰器模式

装饰器模式：扩展功能，原有功能不变且可直接使用
代理模式：显示原有功能，但是经过限制或者阉割之后的
